﻿using System;
using System.Collections.Generic;
using SCG.General;
using SCG.SolarVengeanceEngine.Orders;

namespace SCG.SolarVengeanceEngine.StarShips
{
    //WarShip
    public class WarShip : StarShip
    {
        //Constructor
        public WarShip(SVGame game, Player owner, int engines, int weapons, StarSystem origin)
            : base(game, owner, engines, weapons, origin)
        {
            //Initialize known weapon values
            if (Game != null)
                foreach (Player p in Game.Players)
                    KnownWeapons[p] = 0;
        }

        //Name of StarShip type
        public override string Name
        {
            get
            {
                return "WarShip";
            }
        }

        //description
        public override string Description
        {
            get
            {
                return "WarShips can conquer StarSystems and attack enemy StarShips.  When a WarShip attacks a StarSystem, the StarSystem's Shields are reduced by the WarShip's Weapon rating, and the WarShip is destroyed.  A WarShip can damage or destroy another WarShip only if the target has a lower Weapons rating.";
            }
        }

        //type
        public override StarShipType ShipType
        {
            get
            {
                return StarShipType.WarShip;
            }        
        }

        //can conquer
        public override bool CanConquerStarSystems
        {
            get
            {
                return true;
            }
        }

        //CommandInfluence exterted by CommandShips in range
        public int CommandInfluence { get; set; }

        //Effective Weapons rating with CommandInfluence
        public int EffectiveWeapons
        {
            get
            {
                return Value + CommandInfluence;
            }
        }

        //The weapon value known by other players at any point in time
        public Dictionary<Player, int> KnownWeapons
        {
            get
            {
                return _knownWeapons;
            }
        }

        //Return the known weapon value of an unidentified warship
        public override string PrimarySystemMark
        {
            get
            {
                if (DiscoveredByCurrentPlayer)
                    return "W" + EffectiveWeapons;
                else if (KnownWeapons[Game.CurrentPlayer] > 0)
                    return "W" + KnownWeapons[Game.CurrentPlayer] + "?";
                else
                    return "";
            }
        }
        public override string PrimarySystemStatLabel
        {
            get
            {
                if (Value < MaxValue)
                    return EffectiveWeapons + "/" + (MaxValue + CommandInfluence);
                else
                    return EffectiveWeapons.ToString();
            }
        }

        //Attack adjacent on by default
        public override bool AttackAdjacentDefault
        {
            get
            {
                return true;
            }
        }

        //additional order types
        public override bool CanExecuteOrder(OrderType ot)
        {
            switch (ot)
            {
                case OrderType.Defend:
                case OrderType.DefendPoint:
                case OrderType.TargetStarSystem:
                case OrderType.TargetStarShip:
                case OrderType.AttackAdjacent:
                    return true;
                default:
                    return base.CanExecuteOrder(ot);
            }
        }

        //can it target a specific StarShip?
        public override bool CanTargetStarShip(StarShip ship, bool respectAlliance)
        {
            if (respectAlliance)
                return !Owner.FriendlyTo(ship.Owner);
            else
                return !ship.OwnedByCurrentPlayer;
        }

        //Clear command influence
        protected internal override void Initialize()
        {
            CommandInfluence = 0;
        }

        //Target a StarSystem logic
        protected override void TargetAdjacentStarSystem(StarSystem system)
        {
            Player originalOwner = system.Owner;

            //Report the attack to the host
            if (Game.Host != null)
                Game.Host.StarSystemAttacked(system, Owner);

            //Submit state change
            Game.SubmitStateChange(StateChange.AttackStarSystem, system, Owner);      

            //Perform the attack
            if (EffectiveWeapons > system.Shields)
            {
                Game.ConquerStarSystem(Owner, system);
            }
            else
            {
                system.Shields -= EffectiveWeapons;
                Game.SubmitStateChange(StateChange.SetShields, system, system.Shields);
            }

            //Destroy the attacker
            Game.DestroyStarShip(this);
        }      

        //Attacking a StarShip
        protected override void TargetAdjacentStarShip(StarShip target)
        {
            //warship attacking warship
            if (target is WarShip)
            {
                WarShip targetWS = target as WarShip;
                if (EffectiveWeapons <= targetWS.EffectiveWeapons)
                {
                    //attacker was destroyed
                    if (target is WarShip)
                    {
                        targetWS = target as WarShip;
                        targetWS.SetKnownWeaponValue(Owner, EffectiveWeapons);
                    }  
                    Game.DestroyStarShip(this);
                    return;
                }
            }

            //damage/destroy target
            target.Damage(SVGame.RNG.Next(EffectiveWeapons) + 1, true);
            if (target.Destroyed)
                if (Order != null && Order.OrderType == OrderType.TargetStarShip)
                {
                    MapObjectOrder moo = Order as MapObjectOrder;
                    if (moo.StarShip == target)
                        Order = null;
                }

            //update defender's knowledge of our weapons
            if (target is WarShip)
            {
                WarShip targetWS = target as WarShip;
                SetKnownWeaponValue(targetWS.Owner, targetWS.EffectiveWeapons + 1);
            }
            else
                SetKnownWeaponValue(target.Owner, 1);

            //advance into opponent's space
            if (target.Destroyed)
                Game.MoveShipTowardPoint(this, target.Location);
        }

        //Can it destroy the enemy?
        public override bool CanDestroy(StarShip target)
        {
            if (target.DiscoveredBy[Owner])
            {
                //know the ship type
                if (target is DoppleShip)
                {
                    DoppleShip dopple = target as DoppleShip;
                    return EffectiveWeapons > dopple.DoppleValue;
                }
                else if (target is WarShip)
                {
                    WarShip targetWS = target as WarShip;
                    return EffectiveWeapons > targetWS.EffectiveWeapons;                
                }
                else if (target.ShipType == StarShipType.EMine)
                    return false;
                else
                    return true;
            }
            else
            {
                //don't know the ship type
                if (target is DoppleShip)
                {
                    DoppleShip dopple = target as DoppleShip;
                    return EffectiveWeapons > dopple.GetDoppleKnownWeapons(Owner);
                }
                else if (target is WarShip)
                {
                    WarShip targetWS = target as WarShip;                 
                    return EffectiveWeapons > targetWS.KnownWeapons[Owner];
                }
                else
                    return true;
            }
        }

        //Set the known weapons value
        private void SetKnownWeaponValue(Player player, int knownValue)
        {
            if (KnownWeapons[player] < knownValue)
            {
                KnownWeapons[player] = knownValue;
                Game.SubmitStateChange(StateChange.SetKnownWeapons, this, player, knownValue);            
            }
        }

        //Persistence
        protected override string SubClassPersist()
        {
            SVTokenizer tok = new SVTokenizer(Game);
            foreach (Player p in Game.Players)
                tok.AppendToken(KnownWeapons[p]);
            return tok.Result;
        }
        protected override void SubClassParse(SVTokenizer tok)
        {
            foreach (Player p in Game.Players)
                KnownWeapons[p] = tok.TokenInt;         
        }

        //Private members
        private Dictionary<Player, int> _knownWeapons = new Dictionary<Player, int>();
    }
}
